<template>
	<div class="graph-container" v-loading="loading">
    <div class="header">
      <el-dropdown @command="handleCommand">
        <span class="el-dropdown-link">
          actions<i class="el-icon-arrow-down el-icon--right"></i>
        </span>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item command="toLeft" :disabled="index === 0">to left</el-dropdown-item>
          <el-dropdown-item command="toRight" :disabled="disabledRight">to right</el-dropdown-item>
          <el-dropdown-item command="calculating" :disabled="setting.datecolmn.length === 0">calculating</el-dropdown-item>
          <el-dropdown-item command="setting">setting</el-dropdown-item>
          <el-dropdown-item command="export csv">export csv</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
    </div>
    <base-charts
      ref="charts"
      :base-charts-data="options"
      :graph-key="graphKey"
      @dataZoom="onDataZoom"
      @dataClick="onDataClick"
    ></base-charts>
    <setting-dialog
      ref="settingDialog"
      :visible.sync="settingVisible"
      :setting="setting"
      @save="onSaveSetting"
    ></setting-dialog>
    <calculating-dialog
      :visible.sync="calculatingVisible"
      :zoom-start="zoomStart"
      :zoom-end="zoomEnd"
      :data="originResponse"
      :column="setting.datecolmn"
    ></calculating-dialog>
  </div>
</template>

<script>
import BaseCharts from '@/components/Charts/BaseCharts'
import { getGraphData, exportData } from '@/api'
import SettingDialog from '@/components/SettingDialog'
import CalculatingDialog from '@/components/CalculatingDialog'
import { graphType } from '@/components/constant'
import moment from 'moment'

export default {
  name: 'Graph',
  components: {
    BaseCharts,
    SettingDialog,
    CalculatingDialog
  },
  props: {
    vin: {
      type: String
    },
    graph: {
      type: Object,
      default: () => {}
    },
    index: {
      type: Number,
      default: 0
    },
    disabledRight: {
      type: Boolean,
      default: true
    },
    tripid: {
      type: String,
      default: null
    },
    graphKey: {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      start:null,
      options: {},
      settingVisible: false,
      signalVisible: false,
      calculatingVisible: false,
      setting: {
        name: "",
        graphtype: "line",
        graphx: null,
        graphy: null,
        plotsampling: null,
        datecolmn: []
      },
      loading: false,
      originResponse: [],
      zoomStart: 0,
      zoomEnd: 100,
      startTime: null,
      timer: null
    }
  },
  watch: {
    themeMode(val) {
      this.$refs.charts.reInitChart(val)
      this.initOverview(this.originResponse, true)
    }
  },
  computed: {
    themeMode() {
      return this.$store.state.themeMode
    },
    signals() {
      return this.$store.state.signals
    }
  },
  async mounted() {
    await this.init()
  },
  beforeDestroy() {
    clearInterval(this.timer)
    this.$store.commit("addGraphSignal", {
      key: this.graphKey,
      data: {}
    })
  },
  beforeUnmount() {
    clearInterval(this.timer)
  },
  methods: {
    handleCommand(command) {
      switch (command) {
        case "toLeft":
          this.move('left');
          break;
        case "toRight":
          this.move("right");
          break;
        case "calculating":
          this.calculatingVisible = true;
          break;
        case "setting":
          this.settingVisible = true;
          break;
        case "export csv":
          this.handleExport();
          break;
        default:
          console.log(command)
      }
    },
    async init() {
      const config = this.graph
      this.setting = {
        ...config
      }
      this.originResponse = []
      if (this.setting.datecolmn.length) {
        await this.getGraphData()
      }
    },
    async getGraphData() {
      // 行程查询
      if (this.tripid) {
        // 行程结束
        this.loading = true
        const params = {
          vin: this.vin,
          tripid: this.tripid,
          keys: this.setting.datecolmn.map(v => v.key).join(','),
          keys1: this.setting.datecolmn.map(v => v.key).join(','),
          plotSampling: this.setting.plotsampling
        }
        // 没有选取信号不发送请求
        if (this.setting.datecolmn.length !== 0) {
          let res = await getGraphData(params)
          this.loading = false
          // this.start=res.data.ListData[0].sendingtime
          this.originResponse = Object.freeze(res.data.ListData.map(v => ({
            data: v.sendingtime,
            ...v
          })))
          this.$emit("changeData", {...res.data.LastData,sendingtime:res.data.ListData[res.data.ListData.length - 1].sendingtime,startTime:res.data.ListData[0].sendingtime,flag:true});
          // 保存最新的信号到store
          if (res.data.ListData && res.data.ListData.length) {
            this.$store.commit("addGraphSignal", {
              key: this.graphKey,
              data: res.data.ListData[res.data.ListData.length - 1]
            })
          }
          res = null
          this.initOverview(this.originResponse, true)
        } else {
          this.loading = false
          this.originResponse = []
          this.$store.commit("addGraphSignal", {
            key: this.graphKey,
            data: {}
          })
          this.initOverview(this.originResponse, true)
        }
      } else {
        this.timer && clearInterval(this.timer)
        this.loop()
      }
    },
    async getData(init = true) {
      const params = {
        vin: this.vin,
        keys: this.setting.datecolmn.map(v => v.key).join(','),
        plotSampling: this.setting.plotsampling
      }
      if (this.startTime) {
        params.startTime = this.startTime
      }
      const res = await getGraphData(params)
      // 这里没有tripID，需要看是否需要修改数据结构
      let arr = this.originResponse
      if (res.data.ListData?.length) {
        this.startTime = res.data.ListData[res.data.ListData.length - 1].sendingtime
        arr = res.data.ListData.map(v => ({
          data: v.sendingtime,
          ...v
        }))
        this.$emit("changeData", {...res.data.LastData,sendingtime:res.data.ListData[res.data.ListData.length - 1].sendingtime,startTime:res.data.ListData[0].sendingtime,flag:true});
      }
			this.originResponse = Object.freeze(this.originResponse.concat(arr))
      // 初次
      if (res.data.ListData?.length && this.startTime === res.data.ListData[res.data.ListData.length - 1].sendingtime) {
        this.initOverview(this.originResponse, init)
      } else {
        const { series } = this.generateOption(this.setting.xAxisTick, this.originResponse)
        this.setData(series)
      }
    },
    handleExport() {
      const params = {
        vin: this.vin,
        keys: this.setting.datecolmn.map(v => v.key).join(','),
        tripid: this.tripid,
      }
      window.open(`/platform/a/monitor/tripreport/getRepaortDataFile?vin=${params.vin}&keys=${params.keys}&tripid=${params.tripid}`)
      // exportData(params)
      // 	.then(res => {
      // 		blobDownLoad(res.data, "1")
      // 	})
    },
    async loop() {
      await this.getData()
      this.timer = setInterval(() => {
        this.getData()
      }, this.setting.plotsampling * 1000)
    },
    initOverview(data, init) {
      const { legend, title, tooltip, grid, xAxis, yAxis, visualMap, series, dataZoom } = this.generateOption(this.setting.xAxisTick, data)
      this.$refs.charts.setOptions({
        legend,
        title,
        tooltip,
        grid,
        xAxis,
        yAxis,
        dataZoom,
        series: init ? series : series.map(v => ({
          ...v,
          data: []
        })),
        visualMap
      })
      this.getUnit()
    },
    getUnit() {
      this.$nextTick(() => {
        const extent = this.$refs.charts.getChart().getModel().getComponent("xAxis").axis.scale._extent
        const ticks = this.$refs.charts.getChart().getModel().getComponent("xAxis").axis.scale.getTicks()
        let i = ticks.findIndex(v => v.value === extent[0])
        ticks.splice(i, 1)
        i = ticks.findIndex(v => v.value === extent[1])
        ticks.splice(i, 1)
        let start = moment(ticks[1].value)
        let end = moment(ticks[0].value)
        this.$refs.charts.setOptions({
          xAxis: {
            name: moment.utc(start.diff(end)).format("HH:mm:ss")
          }
        },false)
      })
    },
    setData(series = []) {
      const option = {
        series: series.map(v => ({
          name: v.name,
          data: v.data
        }))
      }
      this.$refs.charts.setOptions(option)
    },
    generateOption(type = 1, data) {
      this.start=data[0]?.sendingtime // 相对时间时，获取图标第一个数据的x轴的时间数据
      // 绝对
      if (type === 1) {
        const xAxis = data.length ? {
          name: "",
          type: "time",
          boundaryGap: false,
          splitLine: {
            show: true
          },
          axisTick: {
            show: true
          },
          axisLabel: {
            show: true,
            formatter: '{HH}:{mm}:{ss}'
          }
        } : {}
        const filterYAxis = this.setting.datecolmn.filter(v => v.visible === undefined ? true : v.visible) || []
        const yAxis = this.setting.datecolmn.length ? this.setting.datecolmn.map((v, i) => ({
          type: 'value',
          show: v.visible === undefined ? true : v.visible,
          name: this.signals.filter(k => k.column === v.key)[0].unit || "",
          offset: filterYAxis.findIndex(k => k.key === v.key)*55,
          axisLabel: {
            show: true
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: v.color
            }
          },
          axisTick: {
            show: true
          },
          splitNumber: parseInt(this.setting.graphy),
          alignTicks: true,
          position: "left",
          min: v.minvalue,
          max: v.maxvalue,
          splitLine: {
            show: i === 0
          },
          dataZoom: [
            {
              type: "slider",
              start: this.zoomStart,
              end: this.zoomEnd
            }
          ]
        })) : {}
        return {
          legend: {
            data: this.setting.datecolmn.map((v) => ({
              name: v.keyname,
              itemStyle: {
                color: v.color
              },
              lineStyle: {
                color: v.color
              }
            })),
            right: "80"
          },
          title: {
            text: this.setting.name
          },
          tooltip: {
            trigger: 'axis',
            appendToBody: true
          },
          grid: {
            left: this.setting.datecolmn.filter(v => v.visible === undefined ? true : v.visible).map(v => v.key).length * 55,
            right: "65"
          },
          dataZoom: [
            {
              type: "slider",
              start: this.zoomStart,
              end: this.zoomEnd
            }
          ],
          xAxis,
          yAxis,
          series: this.setting.datecolmn.map((v, i) => ({
            name: v.keyname,
            type: graphType[this.setting.graphtype],
            data: data.map(d => {
              return {
                name: parseInt(d.data) - parseInt(data[0].data),
                value: [moment.utc(parseInt(d.data)).utcOffset(8).format("YYYY-MM-DDTHH:mm:ss"), d[v.key]]
              }
            }),
            yAxisIndex:i,
            itemStyle: {
              color: v.color,
              opacity: this.setting.graphtype === "1" ? 0 : 1
            },
            lineStyle: {
              width: this.setting.width || 2
            }
          })),
          visualMap: this.setting.datecolmn.map((v, i) => {
            if (v.triggervalue) {
              return {
                top: 50,
                right: 10,
                show: false,
                pieces: [
                  {
                    gt: parseInt(v.minvalue) || 0,
                    lt: parseInt(v.triggervalue) || null,
                    color: v.color
                  },
                  {
                    gte: parseInt(v.triggervalue) || null,
                    color: v.triggerColor || "#c12e34"
                  }
                ],
                outOfRange: {
                  color: v.color
                },
                seriesIndex: i
              }
            } else {
              return {}
            }
          }).filter(v => v.top)
        };
      } else {
        const xAxis = data.length ? {
          name: "",
          type: "value",
          boundaryGap: false,
          splitLine: {
            show: true
          },
          axisTick: {
            show: true
          },
          max: "dataMax",
          axisLabel: {
            show: true,
            formatter: (value) => {
              return value ? moment.duration(value, "ms").format("HH:mm:ss") : "00:00:00"
            }
          }
        } : {}
        const filterYAxis = this.setting.datecolmn.filter(v => v.visible === undefined ? true : v.visible) || []
        const yAxis = this.setting.datecolmn.length ? this.setting.datecolmn.map((v, i) => ({
          type: 'value',
          show: v.visible === undefined ? true : v.visible,
          name: this.signals.filter(k => k.column === v.key)[0].unit || "",
          offset: filterYAxis.findIndex(k => k.key === v.key)*55,
          axisLabel: {
            show: true,
            formatter: (value) => parseInt(value) === parseFloat(value) ? value : value.toFixed(2)
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: v.color
            }
          },
          axisTick: {
            show: true
          },
          splitNumber: parseInt(this.setting.graphy),
          minInterval: 1,
          alignTicks: true,
          position: "left",
          min: v.minvalue,
          max: v.maxvalue,
          splitLine: {
            show: i === 0
          }
        })) : {}
        return {
          legend: {
            data: this.setting.datecolmn.map((v) => ({
              name: v.keyname,
              itemStyle: {
                color: v.color
              },
              lineStyle: {
                color: v.color
              }
            })),
            right: "80"
          },
          title: {
            text: this.setting.name
          },
          tooltip: {
            trigger: 'axis',
            formatter: function(params) {
              let res = "<div><p>"  + params[0].name + "</p></div>";
              for (let i = 0; i < params.length; i++) {
                if (params[i].data != undefined) {
                  res +=
                    "<p>" + params[i].marker  + params[i].seriesName + ":" + params[i].data.value[1] + "</p>";
                }
              }
              return res;
            }
          },
          grid: {
            left: this.setting.datecolmn.filter(v => v.visible === undefined ? true : v.visible).map(v => v.key).length * 55,
            right: "65"
          },
          dataZoom: [
            {
              type: "slider",
              start: this.zoomStart,
              end: this.zoomEnd
            }
          ],
          xAxis,
          yAxis,
          series: this.setting.datecolmn.map((v, i) => ({
            name: v.keyname,
            type: graphType[this.setting.graphtype],
            data: data.map(d => {
              return {
                name: moment(parseInt(d.data)).utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),
                value: [parseInt(d.data) - parseInt(data[0].data), d[v.key]]
              }
            }),
            yAxisIndex:i,
            itemStyle: {
              color: v.color,
              opacity: this.setting.graphtype === "1" ? 0 : 1
            },
            lineStyle: {
              width: this.setting.width || 2
            }
          })),
          visualMap: this.setting.datecolmn.map((v, i) => {
            if (v.triggervalue) {
              return {
                top: 50,
                right: 10,
                show: false,
                pieces: [
                  {
                    gt: parseInt(v.minvalue) || 0,
                    lt: parseInt(v.triggervalue) || null,
                    color: v.color
                  },
                  {
                    gte: parseInt(v.triggervalue) || null,
                    color: v.triggerColor || "#c12e34"
                  }
                ],
                outOfRange: {
                  color: v.color
                },
                seriesIndex: i
              }
            } else {
              return {}
            }
          }).filter(v => v.top)
        };
      }
    },
    onDataZoom(e) {
      const { start, end } = e
      this.zoomStart = start
      this.zoomEnd = end
      // 是否为相对
      // this.getUnit()
    },
    onDataClick(data) {
      this.$emit("clickData", {data,start:Number(this.start)});
    },
    async onSaveSetting(response) {
      const { data, updateSignal } = response
      // todo 不更改信号不应重新获取数据
      this.setting = {
        ...data
      }
      this.$emit("change",{ ...data })
      if (updateSignal) {
        await this.getGraphData()
      } else {
        this.initOverview(this.originResponse, true)
      }
      this.$refs.settingDialog.loading = false
    },
    move(type) {
      this.$emit("move", type)
    }
  }
}
</script>

<style scoped lang="scss">
.graph-container{
  height: 100%;
  position: relative;
  border: 1px solid #ebebeb;
  border-radius: 3px;
  box-sizing: border-box;
  .header{
    position: absolute;
    width: 100%;
    right: 0;
    text-align: right;
    z-index: 100;
  }
  .el-dropdown-link {
    cursor: pointer;
    color: #409EFF;
  }
  .el-icon-arrow-down {
    font-size: 12px;
  }
}
.dark-mode{
  .graph-container{
    border: 1px solid #4C4D4F;
  }
}
</style>
